/*  Copyright Nate Dierk 2013
 *
 *
 *
 */

#include "GMatrix_nd.h"

///////////////////////////////////////////////////////////////////////////////
// GVector Method Bodies

 	// dot product of vectors
 float GVector::dot(const GVector& v1, const GVector& v2){
 	return v1.fX * v2.fX + 
 	v1.fY * v2.fY + 
 	v1.fZ * v2.fZ;
 }

 	// cross product of vectors
 GVector GVector::cross(const GVector& v1, const GVector& v2){
 	float x = v1.fY * v2.fZ - v1.fZ * v2.fY;
 	float y = v1.fZ * v2.fX - v1.fX * v2.fZ;
 	float z = v1.fX * v2.fY - v1.fY * v2.fZ;

 	return GVector(x,y,z);
 }
	
///////////////////////////////////////////////////////////////////////////////
// GMatrix Method Bodies

 GMatrix GMatrix::inverse() const{
 	float d = det();

 	float d_inv = 1 / d;

 	float m11 = row2.fY * d_inv;
 	float m12 = -1 * row1.fY * d_inv;
 	float m13 = (row1.fY * row2.fZ - row1.fZ * row2.fY) * d_inv;
 	float m21 = -1 * row2.fX * d_inv;
 	float m22 = row1.fX * d_inv;
 	float m23 = -1 * (row1.fX * row2.fZ - row1.fZ * row2.fX) * d_inv;

 	return GMatrix(m11, m12, m13, 
 		m21, m22, m23);
 }

 GVector GMatrix::transform(const GVector& v) const {
 	int x = GVector::dot(row1, v);
 	int y = GVector::dot(row2, v);

 	return GVector(x,y);
 }

 GRect GMatrix::xformRect(const GRect& rect) const {
 	int x1 = GVector::dot(row1, GVector(rect.fLeft, rect.fTop));
 	int y1 = GVector::dot(row2, GVector(rect.fLeft, rect.fTop));

 	int x2 = GVector::dot(row1, GVector(rect.fRight, rect.fBottom));
 	int y2 = GVector::dot(row2, GVector(rect.fRight, rect.fBottom));

 	GRect t = GRect::MakeLTRB(x1,y1,x2,y2);
 	t.sort();
 	return t;
 }

 void GMatrix::precat(const GMatrix& M){
 	*this = multiply(*this, M);
 }

 GMatrix GMatrix::multiply(const GMatrix& m1, const GMatrix& m2) {
 	float m11 = GVector::dot(m1.row1, GVector(m2.row1.fX, m2.row2.fX, 0.0f));
 	float m12 = GVector::dot(m1.row1, GVector(m2.row1.fY, m2.row2.fY, 0.0f));
 	float m13 = GVector::dot(m1.row1, GVector(m2.row1.fZ, m2.row2.fZ, 1.0f));
 	float m21 = GVector::dot(m1.row2, GVector(m2.row1.fX, m2.row2.fX, 0.0f));
 	float m22 = GVector::dot(m1.row2, GVector(m2.row1.fY, m2.row2.fY, 0.0f));
 	float m23 = GVector::dot(m1.row2, GVector(m2.row1.fZ, m2.row2.fZ, 1.0f));

 	return GMatrix(m11, m12, m13, 
 		m21, m22, m23);
 }

 GMatrix GMatrix::scale(float x, float y){
 	return GMatrix(x, 0, 0,
 		0, y, 0);
 }

 GMatrix GMatrix::translate(float x, float y){
 	return GMatrix(1, 0, x,
 		0, 1, y);
 }
